package com.jcl.upload.controller;

import com.jcl.upload.po.CustomFile;
import com.jcl.upload.service.FileService;
import com.jcl.upload.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.List;
import java.util.UUID;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2021/2/3 23:13
 */
@Controller
@RequestMapping("file")
@Slf4j
public class FileController
{
    @Autowired
    private FileService fileService;

    // 设置图片上传路径
    @Value("${file.basePath}")
    private String basePath;

    @RequestMapping("/show")
    public String show()
    {
        return "file";
    }

    /**
     * @param file       文件
     * @param suffix     后缀
     * @param shardIndex 分片下标
     * @param shardSize  分片大小
     * @param shardTotal 分片总数
     * @param size       文件大小
     * @param key        文件标识
     * @Description: 分片上传
     * @return:
     * @Author: 朝花不迟暮
     * @Date: 2021/2/4
     */
    @RequestMapping("/upload")
    @ResponseBody
    public Result upload(MultipartFile file,
                         String suffix,
                         Integer shardIndex,
                         Integer shardSize,
                         Integer shardTotal,
                         Integer size,
                         String key) throws IOException, InterruptedException
    {
        log.info("文件上传开始！");
        //文件的名称
        String name = UUID.randomUUID().toString().replaceAll("-", "");
        // 获取文件的扩展名
        String extension = FilenameUtils.getExtension(name);
        //设置图片新的名字
        String fileName = key + "." + suffix;
        //这个是分片的名字
        String shardName = fileName + "." + shardIndex;
        // 以绝对路径保存重名命后的图片
        File file1 = new File(basePath, shardName);
        if (!file1.exists())
        {
            file1.mkdirs();
        }
        //上传这个图片
        file.transferTo(file1);
        //数据库持久化这个数据
        CustomFile customFile = new CustomFile();
        customFile.setPath(basePath + shardName);
        customFile.setName(name);
        customFile.setSuffix(extension);
        customFile.setSize(size);
        customFile.setCreatedAt(System.currentTimeMillis());
        customFile.setUpdatedAt(System.currentTimeMillis());
        customFile.setShardIndex(shardIndex);
        customFile.setShardSize(shardSize);
        customFile.setShardTotal(shardTotal);
        customFile.setFileKey(key);
        fileService.save(customFile);
        //判断当前是不是最后一个分页 如果不是就继续等待其他分页  合并分页
        if (shardIndex.equals(shardTotal))
        {
            customFile.setPath(basePath + fileName);
            this.merge(customFile);
        }
        return Result.ok("上传成功！！！");
    }

    @RequestMapping("/check")
    @ResponseBody
    public Result check(String key)
    {
        List<CustomFile> check = fileService.check(key);
        //如果这个key存在的话 那么就获取上一个分片去继续上传
        if (check.size() != 0)
        {
            return Result.ok("查询成功", check.get(0));
        }
        return Result.fail("查询失败,可以添加");
    }


    private void merge(CustomFile file) throws FileNotFoundException, InterruptedException
    {
        log.info("分片合并开始");
        String path = file.getPath();
        path = path.replace(basePath, "");
        Integer shardTotal = file.getShardTotal();
        File file1 = new File(basePath + path);
        FileOutputStream fos = new FileOutputStream(file1, true);
        FileInputStream fis = null;
        byte[] bytes = new byte[10 * 1024 * 1024];
        int len;
        try
        {
            for (int i = 0; i < shardTotal; i++)
            {
                fis = new FileInputStream(new File(basePath + path + "." + (i + 1)));
                while ((len = fis.read(bytes)) != -1)
                {
                    fos.write(bytes, 0, len);
                }
            }
        } catch (IOException e)
        {
            log.error("分片合并异常", e);
        } finally
        {
            try
            {
                if (fis != null)
                {
                    fis.close();
                }
                fos.close();
                log.info("IO流关闭");
            } catch (Exception e)
            {
                log.error("IO流关闭", e);
            }
        }
        log.info("分片结束了");
        Thread.sleep(100);
        for (int i = 0; i < shardTotal; i++)
        {
            String filePath = basePath + path + "." + (i + 1);
            File newFile = new File(filePath);
            boolean result = newFile.delete();
            log.info("删除{}，{}", filePath, result ? "成功" : "失败");
        }
        log.info("删除分片结束");
    }
}
